import {
  WebSocketGateway,
  WebSocketServer,
  SubscribeMessage,
  MessageBody,
  ConnectedSocket,
  OnGatewayConnection,
  OnGatewayDisconnect,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { UsersService } from '../users/users.service';
import { MessagesService } from '../messages/messages.service';

@WebSocketGateway({
  cors: {
    origin: '*',
    credentials: true,
  },
})
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer()
  server: Server;

  constructor(
    private usersService: UsersService,
    private messagesService: MessagesService,
  ) {}

  async handleConnection(client: Socket) {
    try {
      const token = client.handshake.auth.token;
      if (!token) {
        client.disconnect();
        return;
      }

      // 这里应该验证JWT token，简化处理
      const userId = this.extractUserIdFromToken(token);
      if (!userId) {
        client.disconnect();
        return;
      }

      client.join(`user_${userId}`);
      await this.usersService.updateStatus(userId, 'online');
      
      // 通知好友用户上线
      const friends = await this.usersService.getFriends(userId);
      friends.forEach(friend => {
        this.server.to(`user_${friend._id}`).emit('friendOnline', {
          userId,
          status: 'online',
          lastSeen: new Date(),
        });
      });

      console.log(`用户 ${userId} 已连接`);
    } catch (error) {
      console.error('连接错误:', error);
      client.disconnect();
    }
  }

  async handleDisconnect(client: Socket) {
    try {
      const userId = this.extractUserIdFromToken(client.handshake.auth.token);
      if (userId) {
        await this.usersService.updateStatus(userId, 'offline');
        
        // 通知好友用户下线
        const friends = await this.usersService.getFriends(userId);
        friends.forEach(friend => {
          this.server.to(`user_${friend._id}`).emit('friendOffline', {
            userId,
            status: 'offline',
            lastSeen: new Date(),
          });
        });
      }
      console.log(`用户 ${userId} 已断开连接`);
    } catch (error) {
      console.error('断开连接错误:', error);
    }
  }

  @SubscribeMessage('sendMessage')
  async handleMessage(
    @MessageBody() data: any,
    @ConnectedSocket() client: Socket,
  ) {
    try {
      const userId = this.extractUserIdFromToken(client.handshake.auth.token);
      const message = await this.messagesService.create({
        ...data,
        senderId: userId,
      });

      // 发送给接收者
      if (data.isGroup) {
        this.server.to(`group_${data.receiverId}`).emit('newMessage', message);
      } else {
        this.server.to(`user_${data.receiverId}`).emit('newMessage', message);
        this.server.to(`user_${userId}`).emit('newMessage', message);
      }

      return { success: true, message };
    } catch (error) {
      return { success: false, error: error.message };
    }
  }

  @SubscribeMessage('typing')
  async handleTyping(
    @MessageBody() data: { receiverId: string; isTyping: boolean; isGroup?: boolean },
    @ConnectedSocket() client: Socket,
  ) {
    const userId = this.extractUserIdFromToken(client.handshake.auth.token);
    
    if (data.isGroup) {
      this.server.to(`group_${data.receiverId}`).emit('typing', {
        userId,
        isTyping: data.isTyping,
      });
    } else {
      this.server.to(`user_${data.receiverId}`).emit('typing', {
        userId,
        isTyping: data.isTyping,
      });
    }
  }

  @SubscribeMessage('markAsRead')
  async handleMarkAsRead(
    @MessageBody() data: { messageIds: string[] },
    @ConnectedSocket() client: Socket,
  ) {
    const userId = this.extractUserIdFromToken(client.handshake.auth.token);
    
    for (const messageId of data.messageIds) {
      const message = await this.messagesService.markAsRead(messageId, userId);
      if (message) {
        this.server.to(`user_${message.senderId}`).emit('messageRead', {
          messageId,
          readBy: userId,
        });
      }
    }
  }

  private extractUserIdFromToken(token: string): string | null {
    // 简化处理，实际应该验证JWT
    try {
      const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
      return payload.sub;
    } catch {
      return null;
    }
  }
}
